package com.tools.scanner.ui.qrcode.creator

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import com.google.android.gms.tasks.Tasks
import com.google.gson.Gson
import com.google.mlkit.vision.common.InputImage
import com.tools.scanner.BaseActivity
import com.tools.scanner.R
import com.tools.scanner.constant.AdLocationConstant
import com.tools.scanner.ad.AdManager
import com.tools.scanner.bean.BarcodeSchema
import com.tools.scanner.database.QrHistory
import com.tools.scanner.database.ScannerDatabase
import com.tools.scanner.databinding.ActivityInputContentBinding
import com.tools.scanner.ui.qrcode.creator.impl.BaseCreateFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateBarcodeFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateCalendarFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateContactFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateEmailFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateGeoFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreatePhoneFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateSmsFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateTextFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateUrlFragment
import com.tools.scanner.ui.qrcode.creator.impl.CreateWifiFragment
import com.tools.scanner.utils.DataReportUtil
import com.tools.scanner.utils.ImageUtil
import com.tools.scanner.utils.QrCodeUtil
import com.tools.scanner.utils.ToastUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit

class InputContentActivity : BaseActivity() {

    companion object {

        private const val INPUT_SCHEME = "input_scheme"

        fun actionStart(context: Context, barcodeSchema: BarcodeSchema) {
            val intent = Intent(context, InputContentActivity::class.java)
            intent.putExtra(INPUT_SCHEME, barcodeSchema.name)
            context.startActivity(intent)
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putString(INPUT_SCHEME, mBarcodeSchema?.name)
    }

    private lateinit var mBinding: ActivityInputContentBinding
    private lateinit var createFragment: BaseCreateFragment
    private val mAdLocation = AdLocationConstant.I_CREATE_CODE

    private var mBarcodeSchema: BarcodeSchema? = null
    private var mQrHistory: QrHistory? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivityInputContentBinding.inflate(layoutInflater)
        setContentView(mBinding.root)

        val schemaName: String? = if (savedInstanceState != null) {
            savedInstanceState.getString(INPUT_SCHEME)
        } else {
            intent.getStringExtra(INPUT_SCHEME)
        }

        if (schemaName == null) {
            finish()
            return
        }

        if (savedInstanceState == null) {
            AdManager.loadInterstitialAd(mAdLocation)
        }

        mBarcodeSchema = BarcodeSchema.valueOf(schemaName)
        createFragment = createFragment(mBarcodeSchema!!)
        supportFragmentManager.beginTransaction().apply {
            replace(mBinding.flContainer.id, createFragment, null)
            commitAllowingStateLoss()
        }

        mBinding.ivBack.setOnClickListener {
            finish()
        }

        mBinding.tvSubmit.setOnClickListener {
            createQrCode()
        }
    }

    private fun createFragment(barcodeSchema: BarcodeSchema): BaseCreateFragment {
        when (barcodeSchema) {
            BarcodeSchema.CALENDER -> {
                return CreateCalendarFragment()
            }

            BarcodeSchema.CONTACT -> {
                return CreateContactFragment()
            }

            BarcodeSchema.EMAIL -> {
                return CreateEmailFragment()
            }

            BarcodeSchema.GEO -> {
                return CreateGeoFragment()
            }

            BarcodeSchema.PHONE -> {
                return CreatePhoneFragment()
            }

            BarcodeSchema.SMS -> {
                return CreateSmsFragment()
            }

            BarcodeSchema.TEXT -> {
                return CreateTextFragment()
            }

            BarcodeSchema.URL -> {
                return CreateUrlFragment()
            }

            BarcodeSchema.WIFI -> {
                return CreateWifiFragment()
            }

            BarcodeSchema.EAN_8,
            BarcodeSchema.EAN_13,
            BarcodeSchema.UPC_E,
            BarcodeSchema.UPC_A,
            BarcodeSchema.CODE_39,
            BarcodeSchema.CODE_93,
            BarcodeSchema.CODE_128,
            BarcodeSchema.ITF,
            BarcodeSchema.PDF_417,
            BarcodeSchema.CODABAR,
            BarcodeSchema.DATA_MATRIX,
            BarcodeSchema.AZTEC -> {
                return CreateBarcodeFragment.newInstance(barcodeSchema)
            }
        }
    }

    private fun createQrCode() {
        val schema = mBarcodeSchema
        if (!createFragment.checkParams() || schema == null) {
            return
        }

        showLoadingDialog()
        lifecycleScope.launch(Dispatchers.IO) {
            val content = createFragment.createQrCodeContent()
            val qrBitmap = QrCodeUtil.createQrCode(content, schema)
            if (qrBitmap == null) {
                createFail(1)
                return@launch
            }

            val dataContent = processBitmap(qrBitmap, schema, content)
            if (dataContent == null) {
                createFail(2)
                return@launch
            }

            val qrFile = ImageUtil.saveToFile(this@InputContentActivity, qrBitmap)
            if (qrFile == null) {
                createFail(3)
                return@launch
            }

            val qrHistory = QrHistory(
                schema = schema,
                content = content,
                formatContent = dataContent,
                photoPath = qrFile.absolutePath,
                isCreate = 1
            )
            ScannerDatabase.get().saveQrHistory(qrHistory)
            mQrHistory = qrHistory

            withContext(Dispatchers.Main) {
                showInterstitialAd()
            }
        }
    }

    private suspend fun createFail(type: Int) {
        withContext(Dispatchers.Main) {
            ToastUtil.showToast(R.string.create_qr_code_fail)
            hideLoadingDialog()
            DataReportUtil.reportCreateQrCodeFail(type)
        }
    }

    private fun processBitmap(
        bitmap: Bitmap,
        schema: BarcodeSchema,
        originalContent: String
    ): String? {
        when (schema) {
            BarcodeSchema.EAN_8,
            BarcodeSchema.EAN_13,
            BarcodeSchema.UPC_E,
            BarcodeSchema.UPC_A,
            BarcodeSchema.CODE_39,
            BarcodeSchema.CODE_93,
            BarcodeSchema.CODE_128,
            BarcodeSchema.ITF,
            BarcodeSchema.PDF_417,
            BarcodeSchema.CODABAR,
            BarcodeSchema.DATA_MATRIX,
            BarcodeSchema.AZTEC -> {
                return originalContent
            }

            else -> {}
        }

        val inputImage = InputImage.fromBitmap(bitmap, 0)
        val resultList = Tasks.await(QrCodeUtil.processBitmap(inputImage), 5, TimeUnit.SECONDS)
        if (resultList.isEmpty()) {
            return null
        }

        val barcode = resultList[0]
        var dataContent: String? = null

        val gson = Gson()
        when (schema) {
            BarcodeSchema.URL -> {
                barcode.url?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.CONTACT -> {
                barcode.contactInfo?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.EMAIL -> {
                barcode.email?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.SMS -> {
                barcode.sms?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.GEO -> {
                barcode.geoPoint?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.PHONE -> {
                barcode.phone?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.CALENDER -> {
                barcode.calendarEvent?.let {
                    dataContent = gson.toJson(it)
                }
            }

            BarcodeSchema.WIFI -> {
                barcode.wifi?.let {
                    dataContent = gson.toJson(it)
                }
            }

            else -> {
                dataContent = barcode.rawValue
            }
        }

        return dataContent
    }

    private fun showInterstitialAd() {
        AdManager.addStepCount(mAdLocation)

        if (!AdManager.isLoadComplete(mAdLocation)) {
            hideLoadingDialog()
            AdManager.loadInterstitialAd(mAdLocation)
            nextAdAction()
            return
        }

        AdManager.subscribeAdShowStatusEvent(mAdLocation, this) {
            if (it.status == AdManager.AdShowStatus.DISMISSED) {
                hideLoadingDialog()
                nextAdAction()
            }
        }

        AdManager.showInterstitialAd(mAdLocation, this)
    }

    private fun nextAdAction() {
        hideLoadingDialog()
        mQrHistory?.let {
            CreateQrCodeActivity.actionStart(this@InputContentActivity, it)
            finish()
        }
    }
}